/**
 *
 */
package br.com.puertorico.model.querybuilder.wrappers;

import br.com.puertorico.model.querybuilder.annotations.Argument;
import br.com.puertorico.model.querybuilder.annotations.Operand;
import br.com.puertorico.model.querybuilder.formatters.BuscaBRUtils;

/**
 * @author daniel
 * @version 1.0.0
 */
public class ArgumentWrapper implements GraphElement {

	private String id;

	private Object value;

	private Argument argument;

	/**
	 * @param argument
	 *            o argumento
	 * @param value
	 *            o valor do argumento
	 */
	public ArgumentWrapper(Argument argument, Object value) {
		id = argument.id();
		this.value = value;
		this.argument = argument;
	}

	/**
	 * @return the id
	 */
	public String getId() {
		return id;
	}

	/**
	 * @return the value
	 */
	public Object getValue() {
		return value;
	}

	/*
	 * (non-Javadoc)
	 * @see
	 * br.ufms.nin.jpa.querybuilder.wrapper.GraphElement#getDependencies()
	 */
	public String[] getDependencies() {
		return argument.dependsOn();
	}

	/*
	 * (non-Javadoc)
	 * @see
	 * br.ufms.nin.jpa.querybuilder.wrapper.GraphElement#getElementId()
	 */
	public String getElementId() {
		return argument.id();
	}

	/*
	 * (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (obj instanceof ArgumentWrapper) {
			return ((ArgumentWrapper) obj).getId().equals(id);
		}
		return false;
	}

	/*
	 * (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		return id.hashCode();
	}

	/**
	 * @param joinId
	 * @return true se o joinId estiver na lista de joins requeridos por este
	 *         argumento
	 */
	public boolean isJoinClauseRequired(String joinId) {
		for (String idLocal : argument.requiredJoinClauses()) {
			if (idLocal.equals("")) {
				continue;
			}
			if (joinId.equals(idLocal)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * @param whereId
	 * @return true se o joinId estiver na lista de joins requeridos por este
	 *         argumento
	 */
	public boolean isWhereClauseRequired(String whereId) {
		for (String idLocal : argument.requiredWhereClauses()) {
			if (idLocal.equals("")) {
				continue;
			}
			if (whereId.equals(idLocal)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * @return as clausulas join requeridas por este argumento
	 */
	public String[] getRequiredJoinClauses() {
		if (argument.requiredJoinClauses().length == 1
				&& argument.requiredJoinClauses()[0].equals("")) {
			return new String[0];
		}
		return argument.requiredJoinClauses();
	}

	/**
	 * @return as clausulas where requeridas por este argumento
	 */
	public String[] getRequiredWhereClauses() {
		if (argument.requiredWhereClauses().length == 1
				&& argument.requiredWhereClauses()[0].equals("")) {
			return new String[0];
		}
		return argument.requiredWhereClauses();
	}

	/**
	 * @return o trecho do where deste argumento
	 */
	public String getWhereClause() {
		StringBuilder whereArgumentPiece = new StringBuilder();
		// tratamento diferencial para quando for String
		if (value instanceof String) {
			switch (argument.formatter()) {
			case UPPER:
				whereArgumentPiece.append("upper(").append(argument.name())
						.append(")");
				value = value.toString().toUpperCase();
				break;
			case LOWER:
				whereArgumentPiece.append("lower(").append(argument.name())
						.append(")");
				value = value.toString().toLowerCase();
				break;
			case BUSCA_BR:
				whereArgumentPiece.append(BuscaBRUtils.codigoBuscaBr(argument
						.name()));
				value = BuscaBRUtils.codigoBuscaBr(value.toString());
				break;
			default:
				whereArgumentPiece.append(argument.name());
				break;
			}
			if (argument.operand().value().contains("LIKE")) {
				whereArgumentPiece.append(" LIKE").append(" :").append(id);
				value = argument.operand().expression().replaceFirst("[\\?]",
						value.toString());
			} else {
				whereArgumentPiece.append(" ").append(
						argument.operand().value().replaceFirst("[\\?]",
								":" + id));
			}
		} else if (argument.operand() == Operand.IS_NULL) {
			whereArgumentPiece.append(argument.name()).append(" ").append(
					"IS NULL");
		} else if (argument.operand() == Operand.IS_NOT_NULL) {
			whereArgumentPiece.append(argument.name()).append(" ").append(
					"IS NOT NULL");
		} else {
			whereArgumentPiece.append(argument.name()).append(" ").append(
					argument.operand().value().replaceFirst("[\\?]", ":" + id));
		}
		return whereArgumentPiece.toString();
	}

	public Argument getArgument() {
		return argument;
	}
}
